package com.ruoyi.web.controller.warning;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.warning.domain.entity.FirewallLog;
import com.ruoyi.warning.domain.entity.PortsCriticalLog;
import com.ruoyi.warning.domain.query.PortQuery;
import com.ruoyi.warning.domain.vo.PortCriticalLogVO;
import com.ruoyi.warning.service.IFirewallLogService;
import com.ruoyi.warning.service.IPortsCriticalLogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 关键链路日志表 前端控制器
 * </p>
 *
 * @author chenhc
 * @since 2025-08-12
 */
@RestController
@RequestMapping("/portsCriticalLog")
@Api(tags = "关键链路日志", description = "用于关键链路日志相关操作的控制器")
public class PortsCriticalLogController {
    @Resource
    private IPortsCriticalLogService portsCriticalLogService;
    @Resource
    private IFirewallLogService firewallLogService;
    @ApiOperation("根据端口和时间获取日志")
    @GetMapping(value = "/getLog")
    public R getLog(PortQuery query)
    {
        return R.ok(
                portsCriticalLogService.list(
                        new LambdaQueryWrapper<PortsCriticalLog>()
                                .eq(PortsCriticalLog::getPortId, query.getPortId())
                                .ge(PortsCriticalLog::getCreateTime, query.getStartTime())
                                .le(PortsCriticalLog::getCreateTime, query.getEndTime())
                                .orderByAsc(PortsCriticalLog::getCreateTime)));
    }

    @PostMapping(value = "/exportExcel", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public void exportExcel(@ModelAttribute PortQuery query, HttpServletResponse response) throws IOException {
        List<PortsCriticalLog> list = portsCriticalLogService.list(new QueryWrapper<PortsCriticalLog>().lambda()
                .eq(PortsCriticalLog::getPortId,query.getPortId())
                .ge(query.getStartTime()!=null,PortsCriticalLog::getCreateTime,query.getStartTime())
                .le(query.getEndTime()!=null,PortsCriticalLog::getCreateTime,query.getEndTime())
                .orderByAsc(PortsCriticalLog::getCreateTime));
        List<FirewallLog> list1 = firewallLogService.list(new LambdaQueryWrapper<FirewallLog>()
                .eq(FirewallLog::getDeviceId,query.getDeviceId())
                .ge(query.getStartTime()!=null,FirewallLog::getCreateTime,query.getStartTime())
                .le(query.getEndTime()!=null,FirewallLog::getCreateTime,query.getEndTime())
                .orderByAsc(FirewallLog::getCreateTime));
        List<PortCriticalLogVO> list2 = new ArrayList<>();
        for(int i=0;i<list.size();i++){
            PortCriticalLogVO vo = new PortCriticalLogVO();
            BeanUtils.copyProperties(list.get(i),vo);
            BeanUtils.copyProperties(list1.get(i),vo);
            if(ObjectUtils.isNotEmpty(vo.getIfSpeed())){
                vo.setIfSpeed(formatSpeed(vo.getIfSpeed()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInUcastPkts())){
                vo.setIfInUcastPkts(formatBytesDecimal(vo.getIfInUcastPkts()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInUcastPktsDelta())){
                vo.setIfInUcastPktsDelta(formatBytesDecimal(vo.getIfInUcastPktsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInUcastPktsRate())){
                vo.setIfInUcastPktsRate(formatSpeed(vo.getIfInUcastPktsRate()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutUcastPkts())){
                vo.setIfOutUcastPkts(formatBytesDecimal(vo.getIfOutUcastPkts()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutUcastPktsDelta())){
                vo.setIfOutUcastPktsDelta(formatBytesDecimal(vo.getIfOutUcastPktsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutUcastPktsRate())){
                vo.setIfOutUcastPktsRate(formatSpeed(vo.getIfOutUcastPktsRate()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInErrors())){
                vo.setIfInErrors(formatBytesDecimal(vo.getIfInErrors()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInErrorsDelta())){
                vo.setIfInErrorsDelta(formatBytesDecimal(vo.getIfInErrorsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInErrorsRate())){
                vo.setIfInErrorsRate(formatSpeed(vo.getIfInErrorsRate()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutErrors())){
                vo.setIfOutErrors(formatBytesDecimal(vo.getIfOutErrors()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutErrorsDelta())){
                vo.setIfOutErrorsDelta(formatBytesDecimal(vo.getIfOutErrorsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutErrorsRate())){
                vo.setIfOutErrorsRate(formatSpeed(vo.getIfOutErrorsRate()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInOctets())){
                vo.setIfInOctets(formatBytesDecimal(vo.getIfInOctets()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInOctetsDelta())){
                vo.setIfInOctetsDelta(formatBytesDecimal(vo.getIfInOctetsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfInOctetsRate())){
                vo.setIfInOctetsRate(formatSpeed(vo.getIfInOctetsRate()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutOctets())){
                vo.setIfOutOctets(formatBytesDecimal(vo.getIfOutOctets()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutOctetsDelta())){
                vo.setIfOutOctetsDelta(formatBytesDecimal(vo.getIfOutOctetsDelta()));
            }
            if(ObjectUtils.isNotEmpty(vo.getIfOutOctetsRate())){
                vo.setIfOutOctetsRate(formatSpeed(vo.getIfOutOctetsRate()));
            }
            list2.add(vo);
        }
        ExcelUtil<PortCriticalLogVO> util = new ExcelUtil<>(PortCriticalLogVO.class);
        util.exportExcel(response, list2, "资产表");
    }

    private String formatSpeed(String speed) {
        Long bps = Long.valueOf(speed);
        if (bps >= 1_000_000_000) {
            // Gbps
            double gbps = (double) bps / 1_000_000_000;
            if (gbps == (long) gbps) {
                return String.format("%.0f Gbps", gbps);
            } else {
                return String.format("%.2f Gbps", gbps);
            }
        } else if (bps >= 1_000_000) {
            // Mbps
            double mbps = (double) bps / 1_000_000;
            if (mbps == (long) mbps) {
                return String.format("%.0f Mbps", mbps);
            } else {
                return String.format("%.2f Mbps", mbps);
            }
        } else if (bps >= 1_000) {
            // Kbps
            double kbps = (double) bps / 1_000;
            if (kbps == (long) kbps) {
                return String.format("%.0f Kbps", kbps);
            } else {
                return String.format("%.2f Kbps", kbps);
            }
        } else {
            // 保持bps
            return bps + " bps";
        }
    }

    private String formatBytesDecimal(String byteString) {
        Long bytes = Long.valueOf(byteString);
        if (bytes >= 1_000_000_000) {
            // GB (1000^3)
            double gb = (double) bytes / 1_000_000_000;
            if (gb == (long) gb) {
                return String.format("%.0f GB", gb);
            } else {
                return String.format("%.2f GB", gb);
            }
        } else if (bytes >= 1_000_000) {
            // MB (1000^2)
            double mb = (double) bytes / 1_000_000;
            if (mb == (long) mb) {
                return String.format("%.0f MB", mb);
            } else {
                return String.format("%.2f MB", mb);
            }
        } else if (bytes >= 1_000) {
            // KB (1000)
            double kb = (double) bytes / 1_000;
            if (kb == (long) kb) {
                return String.format("%.0f KB", kb);
            } else {
                return String.format("%.2f KB", kb);
            }
        } else {
            // 保持bytes
            return bytes + " B";
        }
    }
}
